#include <iostream>
#include <CL/cl.h>
#include <map>
#include <string>
 
int main(int argc, const char * argv[])
{
	cl_int errNum;

	cl_uint numPlatforms;
	constexpr int kMaxPlatformNum = 4;
	cl_platform_id platformID[kMaxPlatformNum];
	errNum=clGetPlatformIDs(kMaxPlatformNum, platformID, &numPlatforms);
	std::cout<< "Platform Numbers: " << numPlatforms << std::endl;

	std::map<cl_device_type, std::string> mapDevType;
	mapDevType[CL_DEVICE_TYPE_CPU] = "CL_DEVICE_TYPE_CPU";
	mapDevType[CL_DEVICE_TYPE_GPU] = "CL_DEVICE_TYPE_GPU";
	mapDevType[CL_DEVICE_TYPE_ACCELERATOR] = "CL_DEVICE_TYPE_ACCELERATOR";
	mapDevType[CL_DEVICE_TYPE_DEFAULT] = "CL_DEVICE_TYPE_DEFAULT";


	for (int i = 0; i < numPlatforms; i++)
	{
		std::cout<< "Platform " << i << ":" << std::endl;
		char pFormStr[256] = {0};
		clGetPlatformInfo(platformID[i], CL_PLATFORM_NAME, sizeof(pFormStr), pFormStr, nullptr);
		std::cout<< "\tName: " << pFormStr << std::endl;
		clGetPlatformInfo(platformID[i], CL_PLATFORM_VENDOR, sizeof(pFormStr), pFormStr, nullptr);
		std::cout<< "\tVendor: " << pFormStr << std::endl;
		clGetPlatformInfo(platformID[i], CL_PLATFORM_VERSION, sizeof(pFormStr), pFormStr, nullptr);
		std::cout<< "\tVersion: " << pFormStr << std::endl;

		constexpr int kMaxDevNum = 4;
		cl_uint numDevs;
		cl_device_id deviceID[kMaxDevNum];
		errNum = clGetDeviceIDs(platformID[i], CL_DEVICE_TYPE_ALL, kMaxDevNum, deviceID, &numDevs);
		std::cout<< "\tDevice Numbers: " << numDevs << std::endl;	
	
		for (int i = 0; i < numDevs; i++)
		{
			std::cout<< "\tDevice " << i << ":" << std::endl;

			char devInfo[256] = {0};
			clGetDeviceInfo(deviceID[i], CL_DEVICE_NAME, sizeof(devInfo), devInfo, nullptr);
			std::cout<< "\t\tName: " << devInfo << std::endl;
			clGetDeviceInfo(deviceID[i], CL_DEVICE_VENDOR, sizeof(devInfo), devInfo, nullptr);
			std::cout<< "\t\tVendor: " << devInfo << std::endl;
			clGetDeviceInfo(deviceID[i], CL_DEVICE_VERSION, sizeof(devInfo), devInfo, nullptr);
			std::cout<< "\t\tVersion: " << devInfo << std::endl;
			clGetDeviceInfo(deviceID[i], CL_DRIVER_VERSION, sizeof(devInfo), devInfo, nullptr);
			std::cout<< "\t\tDriver Version: " << devInfo << std::endl;
			cl_device_type devType;
			clGetDeviceInfo(deviceID[i], CL_DEVICE_TYPE, sizeof(devType), &devType, nullptr);
			std::cout<< "\t\tDevice Type: " << mapDevType[devType] << std::endl;
		}

	}


	std::cout << "Executed program succesfully." << std::endl;

	return 0;
}
